Conversation
Implement an OpenFeature provider that wraps the Mixpanel Python SDK's local or remote feature flags provider, enabling standardized feature flag evaluation via the OpenFeature API. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds variant key passthrough, SDK exception handling (try/except), null variant key tests, and context forwarding to evaluation calls. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Stop mapping targeting_key to distinct_id and nesting attributes under custom_properties. All context attributes are now passed through flat, matching the Java and Go SDKs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- shutdown() now delegates to underlying flags provider - Add shutdown() to LocalFeatureFlagsProvider and RemoteFeatureFlagsProvider - Explicitly pass report_exposure=True to get_variant() - Rename reportExposure to report_exposure in RemoteFeatureFlagsProvider - Add context value unwrapping with whole-number float→int conversion - Update test mock signatures for report_exposure parameter Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Six call sites in remote_feature_flags.py used logging.X() (root logger) instead of logger.X() (module logger), breaking independent log configuration. Consolidate lowercase_keys_and_values and lowercase_only_leaf_nodes into single _casefold_recursive method. Fix incorrect return type annotation and remove unnecessary f-string prefixes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Python's bool is a subclass of int, so isinstance(True, int) returns True. Add early guard to reject bool values when resolving integer or float types, returning TYPE_MISMATCH instead of silently coercing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolve conflicts in local_feature_flags.py and remote_feature_flags.py: - Keep consolidated _casefold_recursive method from branch - Adopt master's %-formatting for logger calls and dict[] type hints - Keep branch's snake_case report_exposure parameter naming Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Restore master's lowercase_keys_and_values/lowercase_only_leaf_nodes methods instead of consolidated _casefold_recursive, and restore master's reportExposure camelCase naming on remote provider. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The openfeature-provider sub-project has its own pyproject.toml and dependencies. Root pytest was collecting its tests (failing on missing openfeature SDK), and root ruff was linting it without proper config. - Add --ignore=openfeature-provider to pytest addopts - Add extend-exclude for openfeature-provider in ruff config - Auto-format provider.py and test_provider.py with ruff Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #156 +/- ##
==========================================
+ Coverage 94.20% 94.87% +0.66%
==========================================
Files 9 12 +3
Lines 1554 1930 +376
Branches 100 116 +16
==========================================
+ Hits 1464 1831 +367
- Misses 56 62 +6
- Partials 34 37 +3
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…ant call Let the underlying flags provider use its default behavior rather than explicitly passing report_exposure=True. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Codecov patch/project checks were failing because the openfeature-provider tests weren't generating or uploading coverage data. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The CI coverage upload needs pytest-cov installed to use --cov flags. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| class MixpanelProvider(AbstractProvider): | ||
| """An OpenFeature provider backed by a Mixpanel feature flags provider.""" | ||
|
|
||
| def __init__(self, flags_provider: typing.Any) -> None: |
There was a problem hiding this comment.
Since the primary purpose of the openfeatureprovider is to not have to worry about handling the internals of the providers behind the scene, I think the init should just take in properties we need to initialize the mixpanel library and the requested flags provider
provider = MixpanelProvider(token: str, evaluation_mode: Local|Remote, ..., ..., ... )
There was a problem hiding this comment.
This is a really good point, and for a lot of other OpenFeature providers, it looks like this is how things are handled. I have a couple concerns though (kind of more in a general sense, and not specifically with Python):
- For the client side SDKs, we need to be able to call
mixpanel.identifyto get all the distinctId stuff in - If we create a Mixpanel client within the OpenFeature provider,
mixpanel.trackcalls on the instance outside the provider are no longer passing through the instance that the OpenFeature provider is using, which breaks runtime events' ability to detect those triggers. This will break client SDKs, and will preclude us from implementing the feature on server side SDKs, and incur the wrath of Neha.
I personally don't think it's too painful to pass in the mixpanel client, since it's just one more line, but I do understand that this deviates from the usual pattern. What do you think @efahk ?
- Add PyPy 3.9 and 3.11 to OpenFeature provider CI test matrix - Add error_message to TYPE_MISMATCH flag resolution details - Constrain mixpanel dependency to >=2,<3 - Add ruff linting and formatting config mirroring main project - Fix lint violations (imports, formatting) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The dependency was pinned to mixpanel>=2,<3 but the current SDK version is 5.1.0, causing CI to fail when pip couldn't resolve the constraint. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Design
🤖 Generated with Claude Code